# -*- coding: utf-8 -*-
"""
@author: Laowang
@contact: QQ:1125564921
@Created on: 2022/6/21
@Remark: 
"""

from typing import Optional, List, Dict, Any, Union

from framework_strategy.gopy.trader.object import BaseData, dataclass, field
from framework_strategy.gopy.base.type import Symbol, Price


# ------------------------------
# parameter | request obj
# Generic parameter templates
# The corresponding parameter adjustment needs to be converted in the API function
# If there are too many requirements, you can add them on this basis
# -----------------------------

# test-key
PUBLIC_KEY: str = "c15c7459-b65a-43af-8165-7ac0ae853154"
SECRET_KEY: str = "939a9ccc101f4df7075a1d0cdc2d3f79e88b00bd"

# -----------------------------
# 处理统一请求封装
# 对应平台必须的参数
#   # xt:["a", "b"], bi :["a", "c"]
#

# -----------------------------


@dataclass(init=False)
class ServerTimeData(BaseData):
    """ server time 
    Request parameter criteria
    ::param {

    }
    """
    def xt_init(self, kw):
        return kw

    def binance_init(self, kw):
        return kw

    def xt4_init(self, kw):
        return kw


@dataclass(init=False)
class AccountInfoData(BaseData):
    """ account info """
    PUBLIC_KEY: str = PUBLIC_KEY
    SECRET_KEY: str = SECRET_KEY

    def xt_init(self, kw):
        return kw

    def binance_init(self, kw):
        return kw

    def ftx_init(self, kw):
        return kw


@dataclass(init=False)
class MarketsConfigData(BaseData):
    """ all markets config """

    def xt_init(self, kw):
        return kw

    def binance_init(self, kw):
        return kw

    def ftx_init(self, kw):
        return kw

    def xtfuture_init(self, kw):
        return kw

    def xt4_init(self, kw):
        return kw
    
    def xt4future_init(self, kw):
        return kw

@dataclass(init=False)
class MarketKlineData(BaseData):
    """ market kline """
    market: Symbol
    type: str = "1min"
    since: int = 0
    # binance
    symbol: Symbol
    interval: str = '1m'
    # ftx
    market: Symbol
    resolution: int = 60

    def xt_init(self, kw):
        return kw

    def binance_init(self, kw):
        kw["symbol"] = kw.pop("market")
        kw["interval"] = kw.pop("type", self.interval)
        kw.pop("since") if "since" in kw else ...
        setattr(self, "market", kw["symbol"])
        return kw

    def ftx_init(self, kw):
        kw["resolution"] = kw.pop("type", self.resolution)
        return kw

    def xtfuture_init(self, kw):
        kw["symbol"] = kw.pop("market")
        kw["interval"] = kw.pop("type", self.interval)
        setattr(self, "market", kw["symbol"])
        return kw

    def xt4_init(self, kw):
        kw["symbol"] = kw.pop("market")
        kw["interval"] = kw.pop("type", self.interval)
        setattr(self, "market", kw["symbol"])
        return kw

    def xt4future_init(self, kw):

        if kw.get("market"):
            kw["symbol"] = kw.pop("market")
            setattr(self, "market", kw["symbol"])
        kw["interval"] = kw.pop("type", self.interval)
        return kw


@dataclass(init=False)
class MarketTickerData(BaseData):
    """ market ticker """
    market: Symbol

    def xt_init(self, kw):
        return kw

    def binance_init(self, kw):
        kw["symbol"] = kw.pop("market", [])
        setattr(self, "market", kw["symbol"])
        return kw

    def ftx_init(self, kw):
        return kw

    def xtfuture_init(self, kw):
        if 'market' in kw.keys():
            kw["symbol"] = kw.pop("market")
            setattr(self, "market", kw["symbol"])
        return kw

    def xt4_init(self, kw):
        kw["symbol"] = kw.pop("market")
        setattr(self, "market", kw["symbol"])
        return kw

    def xt4future_init(self, kw):
        if kw.get("market"):
            kw["symbol"] = kw.pop("market")
            setattr(self, "market", kw["symbol"])
        return kw

@dataclass(init=False)
class MarketTickersData(BaseData):
    """ market tickers """
    # binance
    symbol: str = ''
    symbols: field(default_factory=list)

    def xt_init(self, kw):
        return kw

    def binance_init(self, kw):
        return kw
    
    def ftx_init(self, kw):
        return kw
    
    def xt4_init(self, kw):
        return kw

    def xt4future_init(self, kw):
        return kw

@dataclass(init=False)
class MarketDepthData(BaseData):
    """ market depth """
    market: Symbol
    number: int = 20
    # binance
    symbol: Symbol
    # ftx
    depth: int = 35

    def xt_init(self, kw):
        return kw

    def binance_init(self, kw):
        kw["symbol"] = kw.pop("market")
        setattr(self, "market", kw["symbol"])
        return kw

    def ftx_init(self, kw):
        kw["depth"] = kw.pop("number", self.number)
        return kw

    def xtfuture_init(self, kw):
        kw["symbol"] = kw.pop("market")
        setattr(self, "market", kw["symbol"])
        kw["depth"] = kw.pop("number", self.number)
        return kw

    def xt4_init(self, kw):
        kw["symbol"] = kw.pop("market")
        setattr(self, "market", kw["symbol"])
        return kw

    def xt4future_init(self, kw):
        kw["symbol"] = kw.pop("market")
        kw["level"] = kw.pop("number", self.number)
        setattr(self, "market", kw["symbol"])
        return kw
    

@dataclass(init=False)
class MarketTradesData(BaseData):
    """ market trades """
    market: Symbol
    # binance
    symbol: Symbol
    #xt4Spot
    limit: int = 200

    def xt_init(self, kw):
        return kw

    def binance_init(self, kw):
        kw["symbol"] = kw.pop("market")
        setattr(self, "market", kw["symbol"])
        return kw
    
    def ftx_init(self, kw):
        return kw

    def xtfuture_init(self, kw):
        kw["symbol"] = kw.pop("market")
        setattr(self, "market", kw["symbol"])
        return kw

    def xt4_init(self, kw):
        kw["symbol"] = kw.pop("market")
        setattr(self, "market", kw["symbol"])
        return kw

    def xt4future_init(self, kw):
        kw["symbol"] = kw.pop("market")
        kw["num"] = kw.pop("limit", self.limit)
        setattr(self, "market", kw["symbol"])
        return kw


@dataclass(init=False)
class AccountBalanceData(BaseData):
    """ account balance """
    PUBLIC_KEY: str = PUBLIC_KEY
    SECRET_KEY: str = SECRET_KEY
    # xt4Spot

    def xt_init(self, kw):
        kw["PUBLIC_KEY"] = kw.pop("accesskey")
        kw["SECRET_KEY"] = kw.pop("secretkey")
        return kw

    def binance_init(self, kw):
        return kw
    
    def ftx_init(self, kw):
        return kw

    def xtfuture_init(self, kw):
        kw["PUBLIC_KEY"] = kw.pop("accesskey")
        kw["SECRET_KEY"] = kw.pop("secretkey")
        return kw

    def xt4_init(self, kw):
        return kw

    def xt4future_init(self, kw):
        # kw["urlencoded"] = True
        return kw


@dataclass(init=False)
class AccountFundData(BaseData):
    """ account fund """
    PUBLIC_KEY: str = PUBLIC_KEY
    SECRET_KEY: str = SECRET_KEY

    def xt_init(self, kw):
        kw["PUBLIC_KEY"] = kw.pop("accesskey")
        kw["SECRET_KEY"] = kw.pop("secretkey")
        return kw
    
    def binance_init(self, kw):
        return kw

    def xt4_init(self, kw):
        return kw

    def xt4future_init(self, kw):
        kw["urlencoded"] = True
        return kw

@dataclass(init=False)
class AccountSendOrderData(BaseData):
    """ send order """
    # xt
    market: Symbol
    price: Price
    type: int
    number: float
    entrustType: int
    PUBLIC_KEY: str = PUBLIC_KEY
    SECRET_KEY: str = SECRET_KEY
    # binance
    symbol: Symbol
    quantity: int = 0
    side: str = 'BUY'
    type: str = 'LIMIT'
    # ftx
    size: float = 0.
    # XT4SPOT
    # timeInForce:str = "IOC"
    # bizType: str = "SPOT"

    def xt_init(self, kw):
        kw["PUBLIC_KEY"] = kw.pop("accesskey")
        kw["SECRET_KEY"] = kw.pop("secretkey")
        return kw

    def binance_init(self, kw):
        kw["symbol"] = kw.pop("market")
        kw["quantity"] = kw.pop("number")
        kw["side"] = 'BUY' if kw.pop("type") == 1 else 'SELL'
        kw["type"] = 'LIMIT' if kw.pop("entrustType") == 0 else 'MARKET'
        setattr(self, "market", kw["symbol"])
        return kw

    def ftx_init(self, kw):
        kw["size"] = kw.pop("number")
        kw["side"] = 'buy' if kw.pop("type") == 1 else 'sell'
        kw["type"] = 'limit' if kw.pop("entrustType") == 0 else 'market'
        return kw

    def xtfuture_init(self, kw):
        kw["PUBLIC_KEY"] = kw.pop("accesskey")
        kw["SECRET_KEY"] = kw.pop("secretkey")
        kw["symbol"] = kw.pop("market")
        setattr(self, "market", kw["symbol"])
        return kw

    def xt4_init(self, kw):
        kw["quantity"] = kw.pop("number",0.1)
        kw["side"] = 'BUY' if kw.pop("type", 0) == 1 else 'SELL'
        kw["type"] = 'LIMIT' if kw.pop("entrustType", 1) == 0 else 'MARKET'
        kw["symbol"] = kw.pop("market")
        kw["timeInForce"] = kw.get("timeInForce", "GTC")
        kw["bizType"] = kw.get("bizType", "SPOT")
        setattr(self, "market", kw["symbol"])
        return kw

    def xt4future_init(self, kw):
        kw["symbol"] = kw.pop("market")
        kw["orderSide"] = 'BUY' if kw.pop("type", 0) == 1 else 'SELL'
        kw["orderType"] = 'LIMIT' if kw.pop("entrustType", 1) == 0 else 'MARKET'
        kw["origQty"] = kw.pop("number")

        setattr(self, "market", kw["symbol"])
        return kw
    

@dataclass(init=False)
class AccountSendOrdersData(BaseData):
    """ send orders """
    market: Symbol
    data: List[Dict[str, Any]]
    PUBLIC_KEY: str = PUBLIC_KEY
    SECRET_KEY: str = SECRET_KEY
    # XT4SPOT

    def xt_init(self, kw):
        kw["PUBLIC_KEY"] = kw.pop("accesskey")
        kw["SECRET_KEY"] = kw.pop("secretkey")
        return kw

    def binance_init(self, kw):
        return kw

    def xt4_init(self, kw):
        kw["items"] = kw.pop("data", [])
        return kw


@dataclass(init=False)
class AccountCancelOrderData(BaseData):
    """ cancel order """
    # xt
    market: Symbol
    id: Union[str, int]
    PUBLIC_KEY: str = PUBLIC_KEY
    SECRET_KEY: str = SECRET_KEY
    # ftx
    order_id: str = ''

    def xt_init(self, kw):
        kw["PUBLIC_KEY"] = kw.pop("accesskey")
        kw["SECRET_KEY"] = kw.pop("secretkey")
        return kw

    def binance_init(self, kw):
        kw["symbol"] = kw.pop("market")
        kw['orderId'] = kw.pop("id")
        setattr(self, "market", kw["symbol"])
        return kw

    def ftx_init(self, kw):
        kw['order_id'] = kw.pop("id")
        return kw

    def xtfuture_init(self, kw):
        kw["PUBLIC_KEY"] = kw.pop("accesskey")
        kw["SECRET_KEY"] = kw.pop("secretkey")
        if 'market' in kw.keys():
            kw["symbol"] = kw.pop("market")
            setattr(self, "market", kw["symbol"])
        return kw

    def xt4_init(self, kw):
        kw["orderId"] = int(kw.pop("id"))
        kw["urlencoded"] = True
        return kw


@dataclass(init=False)
class AccountCancelOrdersData(BaseData):
    """ cancel orders """
    market: Symbol
    data: List[Union[str, int]]
    PUBLIC_KEY: str = PUBLIC_KEY
    SECRET_KEY: str = SECRET_KEY

    def xt_init(self, kw):
        kw["PUBLIC_KEY"] = kw.pop("accesskey")
        kw["SECRET_KEY"] = kw.pop("secretkey")
        return kw

    def binance_init(self, kw):
        return kw

    def xt4_init(self, kw):
        kw["orderIds"] = kw.pop("data")
        return kw

@dataclass(init=False)
class AccountOrderData(BaseData):
    """ get order """
    # xt
    market: Symbol
    id: int
    PUBLIC_KEY: str = PUBLIC_KEY
    SECRET_KEY: str = SECRET_KEY
    # ftx
    order_id: str = ''

    def xt_init(self, kw):
        kw["PUBLIC_KEY"] = kw.pop("accesskey")
        kw["SECRET_KEY"] = kw.pop("secretkey")
        return kw

    def binance_init(self, kw):
        return kw

    def ftx_init(self, kw):
        kw['order_id'] = kw.pop("id")
        return kw
    
    def xtfuture_init(self, kw):
        if 'market' in kw.keys():
            kw["symbol"] = kw.pop("market")
            setattr(self, "market", kw["symbol"])
        return kw


@dataclass(init=False)
class AccountOpenOrderData(BaseData):
    """ get open order """
    # xt
    market: Symbol
    page: Union[str, int] = "1"
    pageSize: Union[str, int] = "10"
    PUBLIC_KEY: str = PUBLIC_KEY
    SECRET_KEY: str = SECRET_KEY
    # ftx

    def xt_init(self, kw):
        kw["PUBLIC_KEY"] = kw.pop("accesskey")
        kw["SECRET_KEY"] = kw.pop("secretkey")
        return kw

    def binance_init(self, kw):
        kw["symbol"] = kw.pop("market")
        setattr(self, "market", kw["symbol"])
        return kw

    def ftx_init(self, kw):
        return kw

    def xtfuture_init(self, kw):
        kw["PUBLIC_KEY"] = kw.pop("accesskey")
        kw["SECRET_KEY"] = kw.pop("secretkey")
        kw["symbol"] = kw.pop("market")
        setattr(self, "market", kw["symbol"])
        return kw
    
    def xt4_init(self, kw):
        if kw.get("market"):
            kw["symbol"] = kw.pop("market")
        kw["urlencoded"] = True
        return kw


@dataclass(init=False)
class AccountOrdersData(BaseData):
    """ get orders """
    market: Symbol
    data: List[Union[str, int]]
    PUBLIC_KEY: str = PUBLIC_KEY
    SECRET_KEY: str = SECRET_KEY

    def xt_init(self, kw):
        kw["PUBLIC_KEY"] = kw.pop("accesskey")
        kw["SECRET_KEY"] = kw.pop("secretkey")
        return kw

    def binance_init(self, kw):
        kw["symbol"] = kw.pop("market")
        kw['orderId'] = kw.pop("id")
        setattr(self, "market", kw["symbol"])
        return kw

    def xt4_init(self, kw):
        kw["urlencoded"] = True
        kw["orderIds"] = kw.pop("data", [])
        return kw

@dataclass(init=False)
class AccountMineOrdersData(BaseData):

    limit: int
    startTime: int
    endTime: int
    fromId: int

    market: Symbol
    PUBLIC_KEY: str = PUBLIC_KEY
    SECRET_KEY: str = SECRET_KEY

    def xt_init(self, kw):
        kw["PUBLIC_KEY"] = kw.pop("accesskey")
        kw["SECRET_KEY"] = kw.pop("secretkey")
        return kw
    
    def binance_init(self, kw):
        return kw

    def xt4_init(self, kw):
        if kw.get("market"):
            kw["symbol"] = kw.pop("market")
        kw["urlencoded"] = True
        return kw

# -----------------------------------------------------

"""
构造比配请求的响应数据
1. 构造响应数据对应的回调函数
2. 处理写入DB的IO延迟 : 需要异步处理,
3. 数据驱动需要持续运行

使用队列来做异步处理, 消费队列数据写入
如果数据较多的话,使用多线程来处理

队列考虑使用Deque,并发处理.

"""
